﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using ApplicationLayer;

using Blokus.Controls;
using PersistenceLayer;

namespace Blokus.Scenes
{

    public class SceneNewGame : Scene
    {
        public Color[] playerColors = new Color[8];



        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private SpriteFont menuFont;

        private List<string> menuItems = new List<string>();

        private KeyboardState keyPrevState;
        private GamePadState gpPrevState;
        private MouseState mousePrevState;
        private Texture2D texBG, texGrid, texSquare, texPointer, texPixel, texGamesquare, texStar;
        private Texture2D[] texPeople = new Texture2D[5];
        private float aspectRatio;
        private RenderTarget2D backgroundRenderTarget;
        private TextBox[] editName = new TextBox[6];
        private TextBox btnBack, btnStart, btnDaemon, editTime;

        //private GameDesign

        public int playersSelect = 4;
        public int gameSelect = 0;
        public int[] createRandom = new int[8];
        public bool hasDaemon = false;

        public SceneNewGame()
        {
            for (int ct = 0; ct < 6; ct ++)
                editName[ct] = new TextBox("Player" + (ct+1).ToString(), false, new Rectangle(40+200*ct, 240, 180, 40));
        }
        public override void LoadContent(ContentManager content, GraphicsDeviceManager graphics)
        {
            this.graphics = graphics;
            //load font
            menuFont = content.Load<SpriteFont>("gamefont");
            backgroundRenderTarget = new RenderTarget2D(graphics.GraphicsDevice, 1280, 800);
            spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
            #region textboxes
            for (int ct = 0; ct < 6; ct++)
            {
                editName[ct].GameFont = content.Load<SpriteFont>("gamefont");
                editName[ct].Header = "";
                editName[ct].spriteBatch = spriteBatch;
                editName[ct].backgroundTexture = content.Load<Texture2D>("Textures\\rectangle");
                editName[ct].padding = 10;
                editName[ct].deleteOnFocus = true;
                editName[ct].maxCharLimit = 8;
                editName[ct].colorOnMouseOver = true;
            }
            btnBack = new TextBox("Back", false, new Rectangle(20, 730, (int)menuFont.MeasureString("Back").X + 5, (int)menuFont.MeasureString("Back").Y + 5));
            btnBack.isFocusable = false;
            btnBack.spriteBatch = spriteBatch;
            btnBack.GameFont = menuFont;
            btnBack.colorOnMouseOver = true;
            btnBack.backgroundTexture = content.Load<Texture2D>("Textures\\rectangle");
            btnStart = new TextBox("Start", false, new Rectangle(1100, 730, (int)menuFont.MeasureString("Start").X + 5, (int)menuFont.MeasureString("Start").Y + 5));
            btnStart.isFocusable = false;
            btnStart.spriteBatch = spriteBatch;
            btnStart.GameFont = menuFont;
            btnStart.colorOnMouseOver = true;
            btnStart.backgroundTexture = content.Load<Texture2D>("Textures\\rectangle");
            btnDaemon = new TextBox("Daemon: OFF", false, new Rectangle(250, 630, (int)menuFont.MeasureString("Daemon: OFF").X + 5, (int)menuFont.MeasureString("Daemon: OFF").Y + 5));
            btnDaemon.padding = 8;
            btnDaemon.isFocusable = false;
            btnDaemon.spriteBatch = spriteBatch;
            btnDaemon.GameFont = menuFont;
            btnDaemon.colorOnMouseOver = true;
            btnDaemon.backgroundTexture = content.Load<Texture2D>("Textures\\rectangle");
            editTime = new TextBox("5", false, new Rectangle(160, 630, (int)menuFont.MeasureString("99").X + 5, (int)menuFont.MeasureString("99").Y + 5));
            editTime.intOnly = true;
            editTime.maxCharLimit = 2;
            editTime.padding = 8;
            editTime.spriteBatch = spriteBatch;
            editTime.GameFont = menuFont;
            editTime.colorOnMouseOver = true;
            editTime.Header = "Timer: ";
            editTime.backgroundTexture = content.Load<Texture2D>("Textures\\rectangle");
            #endregion


            texBG = content.Load<Texture2D>("Textures\\background");
            texGrid = content.Load<Texture2D>("Textures\\Grid");
            texSquare = content.Load<Texture2D>("Textures\\Square");
            texPointer = content.Load<Texture2D>("Textures\\Pointer");
            texPixel = content.Load<Texture2D>("Textures\\pixel");
            texGamesquare = content.Load<Texture2D>("Textures\\gamesquare");
            texStar = content.Load<Texture2D>("Textures\\star");
            texPeople[0] = content.Load<Texture2D>("Textures\\People2");
            texPeople[1] = content.Load<Texture2D>("Textures\\People3");
            texPeople[2] = content.Load<Texture2D>("Textures\\People4");
            texPeople[3] = content.Load<Texture2D>("Textures\\People5");
            texPeople[4] = content.Load<Texture2D>("Textures\\People6");
            aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
            resetRandomPreviewPieces();

        }

        public override Blokus.GameState Update(GameTime gameTime)
        {
            //get keys
            GamePadState currGPState = GamePad.GetState(PlayerIndex.One);
            bool kUp = Keyboard.GetState().IsKeyDown(Keys.Up) && !keyPrevState.IsKeyDown(Keys.Up)
                || currGPState.IsButtonDown(Buttons.DPadUp) && !gpPrevState.IsButtonDown(Buttons.DPadUp);
            bool kDown = Keyboard.GetState().IsKeyDown(Keys.Down) && !keyPrevState.IsKeyDown(Keys.Down)
                || currGPState.IsButtonDown(Buttons.DPadDown) && !gpPrevState.IsButtonDown(Buttons.DPadDown);
            bool kLeft = Keyboard.GetState().IsKeyDown(Keys.Left) && !keyPrevState.IsKeyDown(Keys.Left)
                || currGPState.IsButtonDown(Buttons.DPadLeft) && !gpPrevState.IsButtonDown(Buttons.DPadLeft);
            bool kRight = Keyboard.GetState().IsKeyDown(Keys.Right) && !keyPrevState.IsKeyDown(Keys.Right)
                || currGPState.IsButtonDown(Buttons.DPadRight) && !gpPrevState.IsButtonDown(Buttons.DPadRight);
            bool kEnter = Keyboard.GetState().IsKeyDown(Keys.Enter) && !keyPrevState.IsKeyDown(Keys.Enter)
                || currGPState.IsButtonDown(Buttons.A) && !gpPrevState.IsButtonDown(Buttons.A);
            bool kEsc = Keyboard.GetState().IsKeyDown(Keys.Escape) && !keyPrevState.IsKeyDown(Keys.Escape)
                || Keyboard.GetState().IsKeyDown(Keys.Q) && !keyPrevState.IsKeyDown(Keys.Q);


            if (Mouse.GetState().LeftButton == ButtonState.Pressed && mousePrevState.LeftButton != ButtonState.Pressed)
            {
                int mouseX = Mouse.GetState().X;
                int mouseY = Mouse.GetState().Y;
                if (mouseY >= 30 && mouseY <= 158) {
                    for (int ct = 0; ct < 5; ct ++) {
                        if (mouseX >= 86 + 240 * ct && mouseX <= 86 + 240 * ct + 128) {
                            playersSelect = ct + 2;
                            break;
                        }
                    }
                }
                //update games section
                if (mouseX >= 30 && mouseX <= 510)
                {
                    int gmCt = 0;
                    for (int ct = 0; ct < PDesigner.designs.Count; ct++)
                    {
                        GameDesign design = PDesigner.designs[ct];
                        if (design.minPlayers <= playersSelect && design.maxPlayers >= playersSelect)
                        {
                            if (ct != gameSelect)
                            {
                                if (mouseY >= 350 + gmCt * 40 && mouseY <= 390 + gmCt * 40)
                                {
                                    gameSelect = ct;
                                    resetRandomPreviewPieces();
                                    break;
                                }
                            }
                            gmCt++;
                        }
                    }
                }
            }

            for (int ct = 0; ct < playersSelect; ct++)
            {
                editName[ct].Update(gameTime, Mouse.GetState());
                if (editName[ct].Text.Trim() == "" && !editName[ct].hasFocus)
                    editName[ct].Text = "Player" + (ct + 1).ToString();
            }
            if (btnDaemon.Update(gameTime, Mouse.GetState())) {
                hasDaemon = !hasDaemon;
                if (hasDaemon)
                    btnDaemon.Text = "Daemon: ON";
                else
                    btnDaemon.Text = "Daemon: OFF";
            }
            if (btnStart.Update(gameTime, Mouse.GetState()))
            {
                setupNewGame();
                return Blokus.GameState.PLAYING;
            }
            if (btnBack.Update(gameTime, Mouse.GetState()))
                return Blokus.GameState.MENU;
            editTime.Update(gameTime, Mouse.GetState());
            if (editTime.Text.Trim() == "" && !editTime.hasFocus)
                editTime.Text = "5";

            //reset previous keyboard/mouse state
            keyPrevState = Keyboard.GetState();
            gpPrevState = GamePad.GetState(PlayerIndex.One);
            mousePrevState = Mouse.GetState();

            //if (kEnter)
            //    return Blokus.GameState.PLAYING;
            //if (kEsc)
            //    return Blokus.GameState.MENU;
            return Blokus.GameState.NEWGAME;
        }

        private void setupNewGame()
        {
            GameDesign gd = PDesigner.designs[gameSelect].getCopy();
            List<Player> pls = new List<Player>();
            for (int ct = 0; ct < playersSelect; ct++)
            {
                pls.Add(new Player());
                pls[ct].name = editName[ct].Text;
            }
            ScenePlaying.newGameDesign = gd;
            ScenePlaying.newPlayers = pls;
        }

        public override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            //graphics.GraphicsDevice.SetRenderTarget(backgroundRenderTarget);
            spriteBatch.Begin();
            //draw background
            //spriteBatch.Draw(texBG, new Rectangle(0, 0, 1280, 800), Color.White);
            spriteBatch.Draw(texPixel, new Rectangle(0, 0, 1280, 800), colorMiddle);


            //draw player section
            DrawPlayerSection();

            //draw names section
            for (int ct = 0; ct < playersSelect; ct ++)
                editName[ct].Draw();
            DrawSquareWithFill(32, 182, 2, 110, 40, colorDark, Color.White);
            spriteBatch.DrawString(menuFont, "NAMES", new Vector2(35, 177), Color.Black);
            //draw start/back buttons
            btnStart.Draw();
            btnBack.Draw();
            //draw options buttons
            btnDaemon.Draw();
            editTime.Draw();

            //draw games section
            DrawGamesSection();


            //draw preview
            DrawPreviewSection();

            //draw cursor
            //DrawMouseCursor();



            spriteBatch.End();

        }

        public void DrawPlayerSection()
        {
            DrawSquare(20, 20, 10, 1240, 150, colorDark);
            //draw people icons
            for (int ct = 0; ct < 5; ct++)
            {
                if (ct + 2 == playersSelect)
                    DrawSquareWithFill(86 + 240 * ct, 31, 1, 128, 128, colorDark, colorLightest);
                spriteBatch.Draw(texPeople[ct], new Rectangle(86 + 240 * ct, 30, 128, 128), new Rectangle(0, 0, 256, 256), Color.White);
            }
            //draw label at topleft
            DrawSquareWithFill(32, 7, 2, 150, 40, colorDark, Color.White);
            spriteBatch.DrawString(menuFont, "PLAYERS", new Vector2(35, 2), Color.Black);
        }

        public void DrawGamesSection()
        {
            DrawSquare(20, 320, 10, 500, 250, colorDark);
            //draw list of games
            int gmCt = 0;
            for (int ct = 0; ct < PDesigner.designs.Count; ct ++)
            {
                GameDesign design = PDesigner.designs[ct];
                if (design.minPlayers <= playersSelect && design.maxPlayers >= playersSelect)
                {
                    if (ct == gameSelect)
                        spriteBatch.Draw(texPixel, new Rectangle(30, 350 + gmCt*40, 480, 40), colorLightest);
                    spriteBatch.DrawString(menuFont, design.name, new Vector2(35, 345 + gmCt * 40), Color.Black);
                    gmCt++;
                }
            }

            //draw label at topleft
            DrawSquareWithFill(32, 307, 2, 105, 40, colorDark, Color.White);
            spriteBatch.DrawString(menuFont, "GAMES", new Vector2(35, 302), Color.Black);
        }

        public void DrawPreviewSection()
        {
            GameDesign design = PDesigner.designs[gameSelect];
            int cellMax = Math.Max(design.board.numColumns, design.board.numRows);
            int cellSize = 380/cellMax;
            int boardHeight = cellSize*design.board.numRows;
            int boardWidth = cellSize*design.board.numColumns;
            int left = 840;
            int top = 330;
            DrawSquare(left-10, top-10, 10, boardWidth + 20, boardHeight + 20, colorDark);
            //draw game grid with spots -- loop through all cells
            for (int rw = 0; rw < design.board.numRows; rw++)
            {
                for (int col = 0; col < design.board.numColumns; col++)
                {
                    spriteBatch.Draw(texGamesquare, new Rectangle((int)(left + col * cellSize), (int)(top + rw * cellSize), (int)cellSize, (int)cellSize), new Rectangle(0, 0, 32, 32), Color.White);
                }
            }
            foreach (Point p in design.board.unplayable)
            {
                spriteBatch.Draw(texGamesquare, new Rectangle((int)(left + p.X * cellSize), (int)(top + p.Y * cellSize), (int)cellSize, (int)cellSize), new Rectangle(0, 0, 32, 32), Color.Black);
            }
            foreach (Point p in design.board.startingCells)
            {
                spriteBatch.Draw(texStar, new Rectangle((int)(left + p.X * cellSize), (int)(top + p.Y * cellSize), (int)cellSize, (int)cellSize), new Rectangle(0, 0, 32, 32), Color.White);
            }
            //draw pieces preview
            for (int ct = 0; ct < 8; ct ++) {
                if (ct + 1 > design.pieces.Count) 
                    break;
                int startTop = 340;
                int availSize = (int)100;
                int availCell = availSize / 6;
                int startLeft = 520+availSize / 2;
                GamePiece piece = design.pieces[createRandom[ct]];
                int col = ct % 2;
                int rw = ct / 2;
                foreach (Point p in piece.points)
                {
                    spriteBatch.Draw(texGamesquare, new Rectangle((int)(startLeft + availCell/2 + availSize*col + p.X * availCell), (int)(startTop + availCell/2 + rw * availSize + p.Y * availCell), (int)availCell, (int)availCell), Color.Blue);
                }
            }
            //draw label at topleft
            DrawSquareWithFill(527, 307, 2, 150, 40, colorDark, Color.White);
            spriteBatch.DrawString(menuFont, "PREVIEW", new Vector2(530, 302), Color.Black);

        }

        public void resetRandomPreviewPieces() {
            Random random = new Random();
            GameDesign design = PDesigner.designs[gameSelect];
            if (design == null)
                return;
            if (design.pieces == null)
                return;
            for (int ct = 0; ct < Math.Min(8, design.pieces.Count); ct ++) {
                bool repeat = true;
                int nextInt = 0;
                while (repeat) {
                    nextInt = random.Next(design.pieces.Count);
                    repeat = false;
                    for (int c = 0; c < ct; c ++) {
                        if (nextInt == createRandom[c])
                            repeat = true;
                    }
                }
                createRandom[ct] = nextInt;
            }
        }

        public void DrawSquare(int left, int top, int border, int width, int height, Color color)
        {
            spriteBatch.Draw(texPixel, new Rectangle(left, top, width, border), color);
            spriteBatch.Draw(texPixel, new Rectangle(left + width - border, top, border, height), color);
            spriteBatch.Draw(texPixel, new Rectangle(left, top + height - border, width, border), color);
            spriteBatch.Draw(texPixel, new Rectangle(left, top, border, height), color);
        }

        public void DrawSquareWithFill(int left, int top, int border, int width, int height, Color borderColor, Color fillColor)
        {
            spriteBatch.Draw(texPixel, new Rectangle(left + border, top + border, width - 2 * border, height - 2 * border), fillColor);
            DrawSquare(left, top, border, width, height, borderColor);
        }

        public void DrawMouseCursor()
        {
            //draw mouse
//            if (pieceSelected == -1 || Mouse.GetState().X < totalPanelSize) //draw plain cursor
            spriteBatch.Draw(texPointer, new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 20, 20), Color.White);
//            else
//            { //a piece has been selected, so draw the piece -- this still needs to go back to plain when users change their minds
//                MyPiece piece = myGame.players[myGame.currentTurn].pieces[pieceSelected];
//                double ptLeft = -2.5 * gameCellWidth;
//                double ptTop = -2.5 * gameCellHeight;
//                foreach (Point p in piece.points)
//                {
//                    spriteBatch.Draw(texGamesquare, new Rectangle((int)(Mouse.GetState().X + ptLeft + p.X * gameCellWidth), (int)(Mouse.GetState().Y + ptTop + p.Y * gameCellHeight), (int)gameCellWidth, (int)gameCellHeight), myGame.players[myGame.currentTurn].color);
//                }
//            }
        }

        public override void ResetPrevKeys()
        {
            keyPrevState = Keyboard.GetState();
            gpPrevState = GamePad.GetState(PlayerIndex.One);
        }

    }
}
